﻿using MongoDB.Driver;
using Sustainalytics.ClientDW.Entities;
using Sustainalytics.Entities;
using System.Collections.Generic;
using System.Linq;

namespace Sustainalytics.ScreeningTool.Synchronization.Handlers
{
    public class GCOverallCompanySummaryExtendedHandler : IHandler<GCOverallCompanySummaryExtended>
    {
        private const string Separator = ";";

        private readonly GCCurrentQuarter _gcCurrentQuarter;

        public GCOverallCompanySummaryExtendedHandler(GCCurrentQuarter gcCurrentQuarter)
        {
            _gcCurrentQuarter = gcCurrentQuarter;
        }

        public ProjectionDefinition<GCOverallCompanySummaryExtended> GetProjection(ProjectionDefinitionBuilder<GCOverallCompanySummaryExtended> builder) => builder
            .Include(x => x.CompanyProfile.Name)
            .Include(x => x.OverallCompanyAssessment)
            .Include("NonCompliantPrinciples._id")
            .Include("NonCompliantPrinciples.Description")
            .Include(x => x.ReasonForNonCompliance)
            .Include(x => x.NonCompliantSince)
            .Include("WatchListPrinciples._id")
            .Include("WatchListPrinciples.Description")
            .Include(x => x.WatchListSince);

        public IEnumerable<ExtraElement> GetExtraElements(GCOverallCompanySummaryExtended entity) => new ExtraElementList
        {
            { "Overall Global Compact Compliance Status",        entity.OverallCompanyAssessment                                   },
            { "Reason for Non-compliance",                       entity.ReasonForNonCompliance                                     },
            { "Global Compact Principle(s) breached",            entity.NonCompliantPrinciples.JoinStringPrinciples(Separator)     },
            { "Principle Abbr Non-compliant",                    entity.NonCompliantPrinciples.JoinStringPrinciplesAbbr(Separator) },
            { "Non-compliant Since",                             entity.NonCompliantSince.NullIfDefaultValue()                     },
            { "Watchlist (Yes/No)",                              entity.WatchListPrinciples.HasPrinciples()                        },
            { "Global Compact Principles at risk of breach",     entity.WatchListPrinciples.JoinStringPrinciples(Separator)        },
            { "Principle Abbr Watchlist",                        entity.WatchListPrinciples.JoinStringPrinciplesAbbr(Separator)    },
            { "Watchlist Since",                                 entity.WatchListSince.NullIfDefaultValue()                        },
            { "Company Global Compact Watchlist PDF report",     entity.GetWatchlistReportName(_gcCurrentQuarter)                  },
            { "Company Global Compact Non-compliant PDF report", entity.GetNonCompliantReportName(_gcCurrentQuarter)               },
        };
    }

    public static class GCPrincipleTemplateEnumerableExtensions
    {
        public static bool HasPrinciples(this IEnumerable<GCPrincipleTemplate> gcPrincipleTemplates)
            => gcPrincipleTemplates != null && gcPrincipleTemplates.Any();

        public static string JoinStringPrinciples(this IEnumerable<GCPrincipleTemplate> gcPrincipleTemplates, string separator)
            => gcPrincipleTemplates?.Select(x => $"Principle {x?.Id}: {x?.Description}").JoinStrings(separator);

        public static string JoinStringPrinciplesAbbr(this IEnumerable<GCPrincipleTemplate> gcPrincipleTemplates, string separator)
            => gcPrincipleTemplates?.Select(x => $"P{x?.Id}").JoinStrings(separator);
    }

    public static class GCOverallCompanySummaryExtendedExtensions
    {
        public static string GetWatchlistReportName(this GCOverallCompanySummaryExtended entity, GCCurrentQuarter gcCurrentQuarter)
            => entity.GetReportName(entity.WatchListPrinciples, GCAssessment.Watchlist, gcCurrentQuarter);

        public static string GetNonCompliantReportName(this GCOverallCompanySummaryExtended entity, GCCurrentQuarter gcCurrentQuarter)
            => entity.GetReportName(entity.NonCompliantPrinciples, GCAssessment.NonCompliant, gcCurrentQuarter);

        private static string GetReportName(
            this GCOverallCompanySummaryExtended entity,
            IEnumerable<GCPrincipleTemplate> gcPrincipleTemplates,
            GCAssessment assessment,
            GCCurrentQuarter gcCurrentQuarter)
            => gcPrincipleTemplates.HasPrinciples() ? assessment.GetFullReportName(entity.CompanyProfile.Name, gcCurrentQuarter.Date) : null;
    }
}
